package com.cuitrip.storage.prefrence;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.text.TextUtils;

import com.cuitrip.app.MainApplication;
import com.lab.logtrack.AppLog;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;


/**
 *
 * proguard 添加 -keep class com.cuitrip.storage.prefrence.storage.preferences.*$* {*;}，保存内部类。
 */
public abstract class BasePreferences {
    private SharedPreferences mSharedPreferences;
    private List<String> mPreferenceKeys;
    private Class mKeyClass;

    /**
     * @param keyClass 保存preferenceKey的类，key必须是public static的
     */
    protected BasePreferences(Class keyClass) {
        mKeyClass = keyClass;
        reloadSharedPreferencesFromFile();
    }

    protected SharedPreferences getSharedPreferences() {
        if (mSharedPreferences == null) {
            reloadSharedPreferencesFromFile();
        }
        return mSharedPreferences;
    }

    /**
     * 重新从文件加载preference(不能跨进程频繁调用，不然会导致文件被覆盖）
     */
    public void reloadSharedPreferencesFromFile() {
        mSharedPreferences = getSharedPreferences(getPreferenceName());
    }

    /**
     * 要保存的preference的文件名
     *
     * @return
     */
    protected abstract String getPreferenceName();

    /**
     * 读取preferenceKey
     *
     * @return
     */
    private List<String> getPreferenceKeys() {
        if (mPreferenceKeys == null) {
            mPreferenceKeys = getPreferenceKeysFromClass();
        }
        return mPreferenceKeys;
    }

    private static SharedPreferences getSharedPreferences(String name) {
        if (TextUtils.isEmpty(name))
            return null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            return MainApplication.getInstance().getSharedPreferences(name, Context.MODE_MULTI_PROCESS);
        } else {
            return MainApplication.getInstance().getSharedPreferences(name, Context.MODE_PRIVATE);
        }
    }

    private List<String> getPreferenceKeysFromClass() {
        List<String> keys = new ArrayList<String>();
        if (mKeyClass == null) {
            AppLog.e("preferenceKey class not find!");
            return keys;
        }
        Field[] fields = mKeyClass.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                if (field.getType() == String.class) {
                    Object value = field.get(null);
                    keys.add((String) value);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return keys;
    }

    /**
     * 检查当前的key是否归属于这个preference，否则抛错
     *
     * @param key
     */
    private void checkKeys(String key) throws NoSuchKeyException {
        List<String> keys = getPreferenceKeys();
        for (String knowKey : keys) {
            if (knowKey.equals(key)) {
                return;
            }
        }
        throw new NoSuchKeyException();
    }

    public void remove(String key) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().remove(key).commit();
    }

    public void putBoolean(String key, boolean value) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().putBoolean(key, value).commit();
    }

    public void putString(String key, String value) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().putString(key, value).commit();
    }


    public void putFloat(String key, float value) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().putFloat(key, value).commit();
    }

    public void putInt(String key, int value) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().putInt(key, value).commit();
    }

    public void putLong(String key, long value) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().putLong(key, value).commit();
    }

    public void putStringSet(String key, Set<String> value) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
        }
        if (Build.VERSION.SDK_INT < 11) return;
        SharedPreferences sharedPreferences = getSharedPreferences();
        sharedPreferences.edit().putStringSet(key, value).commit();
    }

    public boolean getBoolean(String key, boolean defValue) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
            return defValue;
        }
        return getSharedPreferences().getBoolean(key, defValue);
    }

    public String getString(String key, String defValue) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
            return defValue;
        }
        return getSharedPreferences().getString(key, defValue);
    }

    public float getFloat(String key, float defValue) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
            return defValue;
        }
        return getSharedPreferences().getFloat(key, defValue);
    }

    public int getInt(String key, int defValue) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
            return defValue;
        }
        return getSharedPreferences().getInt(key, defValue);
    }

    public long getLong(String key, long defValue) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
            return defValue;
        }
        return getSharedPreferences().getLong(key, defValue);
    }

    public Set<String> getStringSet(String key, Set<String> defValue) {
        try {
            checkKeys(key);
        } catch (NoSuchKeyException e) {
            AppLog.e("preference no such key!", e);
            return defValue;
        }
        if (Build.VERSION.SDK_INT < 11) return defValue;
        return getSharedPreferences().getStringSet(key, defValue);
    }

    public class NoSuchKeyException extends Exception {
    }
}
